package com.kedacom.ctsp.authz.oauth2.core;

import com.alibaba.fastjson.annotation.JSONField;
import com.google.common.collect.Sets;
import lombok.Data;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Set;

import static com.kedacom.ctsp.authz.oauth2.core.GrantType.*;

/**
 * AccessToken请求
 *
 * @author xuwei
 * @create 2018-05-16 18:57
 **/
@Data
public class AccessTokenRequest implements Serializable {

    @JSONField(name = "grant_type")
    private String grantType;
    private String code;
    @JSONField(name = "client_id")
    private String clientId;
    @JSONField(name = "client_secret")
    private String clientSecret;
    private Set<String> scope;
    @JSONField(name = "redirect_uri")
    private String redirectUri;

    // 简化模式（implicit）会用到 @see HttpImplicitRequest.class
    @JSONField(name = "user_id")
    private Long userId;

    private String username;
    private String password;

    @JSONField(name = "refreshToken")
    private String refreshToken;

    public AccessTokenRequest() {

    }

    public static class RefreshTokenRequestBuilder {

        private AccessTokenRequest request = new AccessTokenRequest();

        public static RefreshTokenRequestBuilder newBuilder() {
            return new RefreshTokenRequestBuilder();
        }

        public RefreshTokenRequestBuilder clientId(String clientId) {
            request.clientId = clientId;
            return this;
        }

        public RefreshTokenRequestBuilder clientSecret(String clientSecret) {
            request.clientSecret = clientSecret;
            return this;
        }

        public RefreshTokenRequestBuilder refreshToken(String refreshToken) {
            request.refreshToken = refreshToken;
            return this;
        }

        public AccessTokenRequest build() {
            request.grantType = REFRESH_TOKEN;
            return request;
        }
    }


    public static class ClientCredentialRequestBuilder {

        private AccessTokenRequest request = new AccessTokenRequest();

        public static ClientCredentialRequestBuilder newBuilder() {
            return new ClientCredentialRequestBuilder();
        }

        public ClientCredentialRequestBuilder clientId(String clientId) {
            request.clientId = clientId;
            return this;
        }

        public ClientCredentialRequestBuilder clientSecret(String clientSecret) {
            request.clientSecret = clientSecret;
            return this;
        }

        public AccessTokenRequest build() {
            request.grantType = CLIENT_CREDENTIALS;
            return request;
        }
    }

    public static class AuthorizationCodeTokenRequestBuilder {

        private AccessTokenRequest request = new AccessTokenRequest();

        public static AuthorizationCodeTokenRequestBuilder newBuilder() {
            return new AuthorizationCodeTokenRequestBuilder();
        }

        public AuthorizationCodeTokenRequestBuilder clientId(String clientId) {
            request.clientId = clientId;
            return this;
        }

        public AuthorizationCodeTokenRequestBuilder clientSecret(String clientSecret) {
            request.clientSecret = clientSecret;
            return this;
        }

        public AuthorizationCodeTokenRequestBuilder code(String code) {
            request.code = code;
            return this;
        }

        public AuthorizationCodeTokenRequestBuilder scopes(Set<String> scopes) {
            request.scope = scopes;
            return this;
        }

        public AuthorizationCodeTokenRequestBuilder scope(String scope) {
            if (request.scope == null) {
                request.scope = Sets.newHashSet();
            }
            request.scope.add(scope);
            return this;
        }

        public AuthorizationCodeTokenRequestBuilder redirectUri(String redirectUri) {
            try {
                request.redirectUri = URLEncoder.encode(redirectUri, "utf-8");
            } catch (UnsupportedEncodingException e) {
            }
            return this;
        }

        public AccessTokenRequest build() {
            request.grantType = AUTHORIZATION_CODE;
            return request;
        }
    }

    public static class PasswordRequestBuilder {

        private AccessTokenRequest request = new AccessTokenRequest();

        public static PasswordRequestBuilder newBuilder() {
            return new PasswordRequestBuilder();
        }

        public PasswordRequestBuilder username(String username) {
            request.username = username;
            return this;
        }

        public PasswordRequestBuilder password(String password) {
            request.password = password;
            return this;
        }

        public PasswordRequestBuilder clientId(String clientId) {
            request.clientId = clientId;
            return this;
        }

        public PasswordRequestBuilder clientSecret(String clientSecret) {
            request.clientSecret = clientSecret;
            return this;
        }

        public PasswordRequestBuilder scopes(Set<String> scopes) {
            request.scope = scopes;
            return this;
        }

        public PasswordRequestBuilder scope(String scope) {
            if (request.scope == null) {
                request.scope = Sets.newHashSet();
            }
            request.scope.add(scope);
            return this;
        }

        public AccessTokenRequest build() {
            request.grantType = PASSWORD;
            return request;
        }
    }
}
